#ifndef BERT_RUNNABLEENTRY_H
#define BERT_RUNNABLEENTRY_H

#include <string>
#include <sstream>
#include "Thread.h"
#include "EntryManager.h"

/**
 * 线程封装，为了连接池管理它 叫做工作线程更适合？
 */
class RunnableEntry : public Thread
{
public:
	/**
	 * Constructor
	 */
	RunnableEntry(const std::string & name="RunnableEntry") : Thread(name)
	{
	}
	/**
	 * Set owner
	 */
	virtual void initPool(void * own_pool)
	{
	}
	/**
	 * All tasks
	 */
	virtual int taskSize() const = 0;
	/**
	 * Max capacity per thread
	 */
	virtual int maxTaskSize() const = 0;
};

template <typename RUNNABLEENTRY>// must have run()
class RunnableManager: public EntryManager
{
	/**
	 * Lock for threads container
	 */
	RWLock rwlock;
	/**
	 * 活动线程
	 */
	std::map<pthread_t, RUNNABLEENTRY *> activeThreads;

public:
	/**
	 * 启动min个线程，但保管max个线程体在基类容器中
	 */
	bool init( int min = 1, int max = 1, const std::string & name = "runnable",void *pool=NULL)
	{
		bool ret = true;
		rwlock.wrlock();
		for (int i=0; i<max; ++i)
		{
			std::ostringstream threadname;
			threadname<<name.c_str()<<"["<<i<<"]";
			RUNNABLEENTRY * r = new RUNNABLEENTRY(threadname.str());
			if ( r != NULL )
			{
				r->initPool(pool);
				if (i < min)
				{
					if ( !r->start() || !activeThreads.insert(std::make_pair(r->getThreadID(), r)).second)
					{
						ret = false;
						break;
					}
				}
				if ( !addEntry(r) )
				{//先把执行体保留
					ret = false;
					break;
				}

			}
			else
			{
				ret = false;
				break;
			}
		}
		rwlock.unlock();
		return ret;
	}

	RUNNABLEENTRY * getAverageOne()
	{
		struct GetBest : public Callback<RUNNABLEENTRY>
		{
			RUNNABLEENTRY * ret;
			bool start_newthread;
			GetBest() : ret(NULL), start_newthread(false)
			{
			}
			bool exec(RUNNABLEENTRY *t)
			{
				if (!t->isAlive())
				{
					if ( !t->start())
						return false;

					start_newthread = true;
					ret = t;
					return false;//我觉得应该是false
				}
				if ( ret == NULL || (t->taskSize() < ret->taskSize()))
						ret = t;
				return true;
			}
		}getBest;
		rwlock.rdlock();
		execEveryEntry<RUNNABLEENTRY>(getBest);//并不遍历完，遇到false终止
		rwlock.unlock();
		if ( getBest.start_newthread && getBest.ret != NULL)
		{
			rwlock.wrlock();
			if (!activeThreads.insert(std::make_pair(getBest.ret->getThreadID(),getBest.ret)).second)
				;//impossible
			else
				;//sucess
			rwlock.unlock();
		}
		else if ( getBest.start_newthread )
			return NULL;//error, some thread start failed
		return getBest.ret;
	}

	RUNNABLEENTRY * getOne()
	{
		struct GetOne : public Callback<RUNNABLEENTRY>
		{
			RUNNABLEENTRY * ret;
			bool start_newthread;
			GetOne() : ret(NULL), start_newthread(false)
			{
			}
			bool exec(RUNNABLEENTRY *t)
			{
				if (!t->isAlive())
				{
					if ( !t->start())
						return false;

					start_newthread = true;
					ret = t;//就此为止，不需要再遍历
					return false;
				}
				if ( t->taskSize() < t->maxTaskSize())
				{
					ret = t;
					return false;//就此为止，不需要再遍历
				}
				return true;
			}
		}getOne;
		rwlock.rdlock();
		execEveryEntry<RUNNABLEENTRY>(getOne);//并不遍历完，遇到false终止
		rwlock.unlock();
		if ( getOne.start_newthread )
		{
			rwlock.wrlock();
			if (!activeThreads.insert(std::make_pair(getOne.ret->getThreadID(),getOne.ret)).second)
				;//impossible
			else
				;//sucess
			rwlock.unlock();
		}
		return getOne.ret;
	}
	/**
	 * 睡眠毫秒
	 */
	int taskCount()
	{
		struct GetSize : public Callback<RUNNABLEENTRY>
		{
			int size;
			GetSize() : size(0)
			{
			}
			bool exec( RUNNABLEENTRY * t)
			{
				if ( t->isAlive() )
					size += t->taskSize();
				return true;
			}
		}exec;
		rwlock.rdlock();
		execEveryEntry<RUNNABLEENTRY>(exec);
		rwlock.unlock();
		return exec.size;
	}

	/**
	 * 终止线程运行
	 */
	void stopAllThreads()
	{
		struct Stop : public Callback<RUNNABLEENTRY>
		{
			bool exec( RUNNABLEENTRY * t)
			{
				if ( t != NULL)
				{
					t->stop();
					t->join();
				}
				return true;
			}
		}exec;
		rwlock.wrlock();
		execEveryEntry<RUNNABLEENTRY>(exec);
		EntryManager::deleteAll();
		rwlock.unlock();
		return ;
	}
};

#endif

